/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dmcn.bl.genetics.execute;

import dmcn.bl.genetics.fitnessfunction.AssignTerminalFitnessFunction;
import dmcn.bl.genetics.genes.Concetrator;
import dmcn.bl.genetics.gui.GuiController;
import dmcn.bl.genetics.input.Input;
import org.jgap.*;
import org.jgap.impl.CrossoverOperator;
import org.jgap.impl.DefaultConfiguration;
import org.jgap.impl.IntegerGene;
import org.jgap.impl.MutationOperator;

/**
 *
 * @author Home
 */
public class ExecuteGenetic {

    Concetrator[] concetratorGenes;
    private int numOfConcetrators;
    private int numOfTerminals;

    public void executeGenetic(Input input,
            int populationSize,
            int numOfEvolves,
            boolean moreOptions,
            int mutation,
            double crossOver,
            double approximationOffset,
            int maxApproximationCount) throws InvalidConfigurationException {
        long startTime = System.currentTimeMillis();
//        this.concetratorGenes = concetratorGenes;
        this.numOfConcetrators = input.getSygkentrotes();
        this.numOfTerminals = input.getPhges();
        Configuration conf = new DefaultConfiguration() {

            FitnessEvaluator evaluator = new DefaultFitnessEvaluator() {

                @Override
                public boolean isFitter(double a_fitness_value1, double a_fitness_value2) {
                    return a_fitness_value2 > a_fitness_value1;
                }
            };

            @Override
            public FitnessEvaluator getFitnessEvaluator() {
                return evaluator;
            }
        };
        if (moreOptions) {
            conf.addGeneticOperator(new CrossoverOperator(conf));//, crossOver));
            conf.addGeneticOperator(new MutationOperator(conf));//, mutation));
        }
        conf.setPreservFittestIndividual(true);
        conf.setKeepPopulationSizeConstant(true);
//        TerminalBulkFitnessFunction bulkFitnessFunction = new TerminalBulkFitnessFunction(input);
//        conf.setBulkFitnessFunction(bulkFitnessFunction);
        AssignTerminalFitnessFunction ff = new AssignTerminalFitnessFunction(input);
        conf.setFitnessFunction(ff);
        //edw bazeis 0,1
        Gene[] sampleGenes = new Gene[numOfConcetrators * numOfTerminals];
        for (int i = 0; i < numOfConcetrators * numOfTerminals; i++) {
            sampleGenes[i] = new IntegerGene(conf, 0, 1);
        }
        IChromosome sampleChromosome = new Chromosome(conf, sampleGenes);
        conf.setSampleChromosome(sampleChromosome);
        conf.setPopulationSize(populationSize);
        Genotype population;
        population = Genotype.randomInitialGenotype(conf);
        IChromosome bestSolutionSoFar;
        
        GuiController guiController = new GuiController(input);
        
//        for (int i = 0; i < numOfEvolves; i++) {
//            population.evolve();
//
//        }
        boolean evolve = true;
        double previousFitness;
        double currentFitness;
        int approximationCount = 0;
        population.evolve();
        while (evolve) {
            previousFitness = population.getFittestChromosome().getFitnessValue();
            population.evolve();
            currentFitness = population.getFittestChromosome().getFitnessValue();
            if (previousFitness - currentFitness < approximationOffset && currentFitness != Integer.MAX_VALUE) {
                approximationCount++;
            } else {
                approximationCount = 0;
            }
            if (approximationCount > maxApproximationCount) {
                evolve = false;
            }
            guiController.setBestSolutionSoFar(population.getFittestChromosome());
            guiController.paint();
        }
        bestSolutionSoFar = population.getFittestChromosome();

        /*
         * print solution to log
         */

        System.out.println("The best solution has a fitness value of "
                + bestSolutionSoFar.getFitnessValue());

        System.out.println("The best solution is: ");
        System.out.print("   ");
        for (int i = 0; i < numOfTerminals; i++) {
            System.out.print((i + 1) + " ");
        }
        System.out.println("");
        int j = 0;
        for (int i = 0; i < bestSolutionSoFar.getGenes().length; i++) {
            if ((i) % numOfTerminals == 0) {
                System.out.print(++j + ": ");
            }
            System.out.print(bestSolutionSoFar.getGenes()[i].getAllele() + " ");
            if ((i + 1) % numOfTerminals == 0) {
                System.out.println("");

            }

        }



//        for (int i = 0; i < this.numOfConcetrators; i++) {
//            this.concetratorGenes[i].setTerminal((Integer) bestSolutionSoFar.getGene(i).getAllele());
//            f.repaint();
//        }
        long endTime = System.currentTimeMillis();
        System.out.println("execute at : " + (endTime - startTime) / 1000 + " seconds");
        Configuration.reset();

    }
//        public Concetrator[] getConcetratorGenes() {
//        return concetratorGenes;
//    }
}
